/**
 * @file control_data.c
 * @brief 遥控数据模块实现
 * @details 本文件实现了104协议的遥控数据处理功能，包括单点命令、双点命令、
 *          带时标的单点命令、带时标的双点命令、调节命令等数据类型的
 *          序列化和反序列化操作。支持完整的数据转换和验证功能。
 * 
 * @author zyb
 * @date 2025-10-11
 * @version 1.0
 * 
 * @note 所有函数都遵循104协议规范，确保严格的数据处理
 * @warning 数据转换失败时应返回相应的错误码，便于上层处理
 * 
 * @see control_data.h
 * @see protocol_types.h
 * @see buffer_utils.h
 * @see time_utils.h
 */

#include "../include/control_data.h"
#include "../../common/types/include/protocol_types.h"
#include "../../../../../common/utils/include/buffer_utils.h"
#include "../../common/utils/include/time_utils.h"
#include "../../common/error/include/error_codes.h"
#include "../../common/utils/include/validation_utils.h"
#include "../../../../../common/logs/include/logger.h"
#include <string.h>

// 定义模块名称
#define LOG_MODULE_NAME "CONTROL_DATA"

/* ==================== 单点命令处理函数实现 ==================== */

/**
 * @brief 单点命令转换为字节数组
 * @details 将单点命令结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param command 单点命令结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_single_command
 * @see validate_single_command_data
 * @see buffer_write_u32
 * @see buffer_write_u8
 */
protocol_error_t single_command_to_bytes(const C_SC_NA_1_t* command,
                                       u8* buffer, u32 buffer_size, u32* actual_length) {
    LOG_DEBUG(LOG_MODULE_NAME, "转换单点命令到字节数组: command=%p, buffer=%p, buffer_size=%u", 
              command, buffer, buffer_size);
    
    if (command == NULL || buffer == NULL || actual_length == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证单点命令 */
    LOG_DEBUG(LOG_MODULE_NAME, "验证信息对象地址: %u", command->info_address);
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象地址: %u", command->info_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象地址验证通过");
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证单点命令品质");
    if (!is_scq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的单点命令品质");
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "单点命令品质验证通过");
    
    /* 检查缓冲区大小 */
    if (buffer_size < 4) { /* 地址(3字节) + SCQ(1字节) */
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %u < 4", buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小检查通过: %u >= 4", buffer_size);
    
    /* 写入信息对象地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入信息对象地址: %u", command->info_address);
    buffer_write_u32(buffer, 0, command->info_address, 0);
    
    /* 写入单点命令品质描述词 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入单点命令品质描述词: 0x%02X", *(u8*)&command->quality);
    buffer[3] = *(u8*)&command->quality;
    
    *actual_length = 4;
    LOG_INFO(LOG_MODULE_NAME, "单点命令成功转换为字节数组，实际长度: %u", *actual_length);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 字节数组转换为单点命令
 * @details 将104协议规定的字节数组格式转换为单点命令结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param command 单点命令结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳单点命令
 * 
 * @see single_command_to_bytes
 * @see validate_single_command_data
 * @see buffer_read_u32
 * @see buffer_read_u8
 */
protocol_error_t bytes_to_single_command(const u8* data, u32 length,
                                        C_SC_NA_1_t* command) {
    LOG_DEBUG(LOG_MODULE_NAME, "从字节数组转换单点命令: data=%p, length=%u, command=%p", 
              data, length, command);
    
    if (data == NULL || command == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 检查数据长度 */
    if (length < 4) { /* 地址(3字节) + SCQ(1字节) */
        LOG_ERROR(LOG_MODULE_NAME, "数据长度太小: %u < 4", length);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "数据长度检查通过: %u >= 4", length);
    
    /* 读取信息对象地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取信息对象地址从缓冲区[0-2]");
    buffer_read_u32(data, 0, (u32*)&command->info_address, 0);
    
    /* 读取单点命令品质描述词 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取单点命令品质描述词从缓冲区[3]");
    memcpy(&command->quality, &data[3], sizeof(scq_t));
    
    LOG_DEBUG(LOG_MODULE_NAME, "读取完成: 地址=%u, SCQ=0x%02X", 
              command->info_address, *(u8*)&command->quality);
    
    /* 验证转换后的数据 */
    LOG_DEBUG(LOG_MODULE_NAME, "验证转换后的数据");
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象地址无效: %u", command->info_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    
    if (!is_scq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "单点命令品质描述词无效: 0x%02X", *(u8*)&command->quality);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "单点命令转换成功: 地址=%u, SCQ=0x%02X", 
             command->info_address, *(u8*)&command->quality);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证单点命令
 * @details 验证单点命令结构的完整性和有效性。
 *          检查地址和品质描述词的有效性。
 * 
 * @param command 单点命令结构，不能为NULL
 * @return 验证结果
 *         - 1: 单点命令有效
 *         - 0: 单点命令无效
 * 
 * @note 验证地址和品质描述词的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_info_address_valid
 * @see is_qos_valid
 * @see C_SC_NA_1_t
 */
int validate_single_command_data(const C_SC_NA_1_t* command) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证单点命令: command=%p", command);
    
    if (command == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "单点命令指针为NULL");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证信息对象地址: %u", command->info_address);
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象地址无效: %u", command->info_address);
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证单点命令品质");
    if (!is_scq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "单点命令品质无效: 0x%02X", *(u8*)&command->quality);
        return 0;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "单点命令验证成功: 地址=%u, 品质=0x%02X", 
             command->info_address, *(u8*)&command->quality);
    return 1;
}

/* ==================== 双点命令处理函数实现 ==================== */

/**
 * @brief 双点命令转换为字节数组
 * @details 将双点命令结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param command 双点命令结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_double_command
 * @see validate_double_command_data
 * @see buffer_write_u32
 * @see buffer_write_u8
 */
protocol_error_t double_command_to_bytes(const C_DC_NA_1_t* command,
                                       u8* buffer, u32 buffer_size, u32* actual_length) {
    LOG_DEBUG(LOG_MODULE_NAME, "转换双点命令到字节数组: command=%p, buffer=%p, buffer_size=%u", 
              command, buffer, buffer_size);
    
    if (command == NULL || buffer == NULL || actual_length == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证双点命令 */
    LOG_DEBUG(LOG_MODULE_NAME, "验证信息对象地址: %u", command->info_address);
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象地址: %u", command->info_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象地址验证通过");
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证双点命令品质");
    if (!is_dcq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的双点命令品质");
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "双点命令品质验证通过");
    
    /* 检查缓冲区大小 */
    if (buffer_size < 4) { /* 地址(3字节) + DCQ(1字节) */
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %u < 4", buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "开始写入双点命令数据到缓冲区");
    
    /* 写入信息对象地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入信息对象地址: %u", command->info_address);
    buffer_write_u32(buffer, 0, command->info_address, 0);
    
    /* 写入双点命令品质描述词 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入双点命令品质描述词: 0x%02X", *(u8*)&command->quality);
    memcpy(&buffer[3], &command->quality, sizeof(dcq_t));
    
    *actual_length = 4;
    LOG_INFO(LOG_MODULE_NAME, "双点命令成功转换为字节数组，实际长度: %u", *actual_length);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 字节数组转换为双点命令
 * @details 将104协议规定的字节数组格式转换为双点命令结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param command 双点命令结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳双点命令
 * 
 * @see double_command_to_bytes
 * @see validate_double_command_data
 * @see buffer_read_u32
 * @see buffer_read_u8
 */
protocol_error_t bytes_to_double_command(const u8* data, u32 length,
                                        C_DC_NA_1_t* command) {
    LOG_DEBUG(LOG_MODULE_NAME, "从字节数组转换双点命令: data=%p, length=%u, command=%p", 
              data, length, command);
    
    if (data == NULL || command == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 检查数据长度 */
    if (length < 4) { /* 地址(3字节) + DCQ(1字节) */
        LOG_ERROR(LOG_MODULE_NAME, "数据长度太小: %u < 4", length);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "数据长度检查通过: %u >= 4", length);
    
    /* 读取信息对象地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取信息对象地址从缓冲区[0-2]");
    buffer_read_u32(data, 0, (u32*)&command->info_address, 0);
    
    /* 读取双点命令品质描述词 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取双点命令品质描述词从缓冲区[3]");
    memcpy(&command->quality, &data[3], sizeof(dcq_t));
    
    LOG_DEBUG(LOG_MODULE_NAME, "读取完成: 地址=%u, DCQ=0x%02X", 
              command->info_address, *(u8*)&command->quality);
    
    /* 验证转换后的数据 */
    LOG_DEBUG(LOG_MODULE_NAME, "验证转换后的数据");
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象地址无效: %u", command->info_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    
    if (!is_dcq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "双点命令品质描述词无效: 0x%02X", *(u8*)&command->quality);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "双点命令转换成功: 地址=%u, DCQ=0x%02X", 
             command->info_address, *(u8*)&command->quality);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证双点命令
 * @details 验证双点命令结构的完整性和有效性。
 *          检查地址和品质描述词的有效性。
 * 
 * @param command 双点命令结构，不能为NULL
 * @return 验证结果
 *         - 1: 双点命令有效
 *         - 0: 双点命令无效
 * 
 * @note 验证地址和品质描述词的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_info_address_valid
 * @see is_diq_valid
 * @see C_DC_NA_1_t
 */
int validate_double_command_data(const C_DC_NA_1_t* command) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证双点命令: command=%p", command);
    
    if (command == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "双点命令指针为NULL");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证信息对象地址: %u", command->info_address);
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象地址无效: %u", command->info_address);
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证双点命令品质");
    if (!is_dcq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "双点命令品质无效: 0x%02X", *(u8*)&command->quality);
        return 0;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "双点命令验证成功: 地址=%u, 品质=0x%02X", 
             command->info_address, *(u8*)&command->quality);
    return 1;
}

/* ==================== 带时标的单点命令处理函数实现 ==================== */

/**
 * @brief 带时标的单点命令转换为字节数组
 * @details 将带时标的单点命令结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化，包含时间戳信息。
 * 
 * @param command 带时标的单点命令结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据序列化，包含时间戳
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_single_command_with_time
 * @see validate_single_command_data_with_time
 * @see buffer_write_u32
 * @see buffer_write_u8
 * @see cp56time2a_to_bytes
 */
protocol_error_t single_command_with_time_to_bytes(const C_SC_TA_1_t* command,
                                                  u8* buffer, u32 buffer_size, u32* actual_length) {
    LOG_DEBUG(LOG_MODULE_NAME, "转换带时标的单点命令到字节数组: command=%p, buffer=%p, buffer_size=%u", 
              command, buffer, buffer_size);
    
    if (command == NULL || buffer == NULL || actual_length == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证带时标的单点命令 */
    LOG_DEBUG(LOG_MODULE_NAME, "验证信息对象地址: %u", command->info_address);
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象地址: %u", command->info_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象地址验证通过");
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证单点命令品质");
    if (!is_scq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的单点命令品质");
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "单点命令品质验证通过");
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证时间戳");
    if (!is_cp56time2a_valid(&command->timestamp)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的时间戳");
        return PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "时间戳验证通过");
    
    /* 检查缓冲区大小 */
    if (buffer_size < 11) { /* 地址(3字节) + SCQ(1字节) + 时间戳(7字节) */
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %u < 11", buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "开始写入带时标的单点命令数据到缓冲区");
    
    /* 写入信息对象地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入信息对象地址: %u", command->info_address);
    buffer_write_u32(buffer, 0, command->info_address, 0);
    
    /* 写入单点命令品质描述词 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入单点命令品质描述词: 0x%02X", *(u8*)&command->quality);
    memcpy(&buffer[3], &command->quality, sizeof(scq_t));
    
    /* 写入时间戳 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入时间戳");
    memcpy(&buffer[4], &command->timestamp, 7);
    protocol_error_t result = PROTOCOL_SUCCESS;
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "时间戳写入失败");
        return result;
    }
    
    *actual_length = 11;
    LOG_INFO(LOG_MODULE_NAME, "带时标的单点命令成功转换为字节数组，实际长度: %u", *actual_length);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 字节数组转换为带时标的单点命令
 * @details 将104协议规定的字节数组格式转换为带时标的单点命令结构。
 *          按照协议规范进行数据反序列化，包含时间戳信息。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param command 带时标的单点命令结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP: 时间戳无效
 * 
 * @note 按照104协议规范进行数据反序列化，包含时间戳
 * @warning 数据长度必须足够容纳带时标的单点命令
 * 
 * @see single_command_with_time_to_bytes
 * @see validate_single_command_data_with_time
 * @see buffer_read_u32
 * @see buffer_read_u8
 * @see bytes_to_cp56time2a
 */
protocol_error_t bytes_to_single_command_with_time(const u8* data, u32 length,
                                                   C_SC_TA_1_t* command) {
    LOG_DEBUG(LOG_MODULE_NAME, "从字节数组转换带时标的单点命令: data=%p, length=%u, command=%p", 
              data, length, command);
    
    if (data == NULL || command == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 检查数据长度 */
    if (length < 11) { /* 地址(3字节) + SCQ(1字节) + 时间戳(7字节) */
        LOG_ERROR(LOG_MODULE_NAME, "数据长度太小: %u < 11", length);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "数据长度检查通过: %u >= 11", length);
    
    /* 读取信息对象地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取信息对象地址从缓冲区[0-2]");
    buffer_read_u32(data, 0, (u32*)&command->info_address, 0);
    
    /* 读取单点命令品质描述词 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取单点命令品质描述词从缓冲区[3]");
    memcpy(&command->quality, &data[3], sizeof(scq_t));
    
    /* 读取时间戳 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取时间戳从缓冲区[4-10]");
    memcpy(&command->timestamp, &data[4], 7);
    protocol_error_t result = PROTOCOL_SUCCESS;
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "时间戳读取失败");
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "读取完成: 地址=%u, 品质=0x%02X", 
              command->info_address, *(u8*)&command->quality);
    
    /* 验证转换后的数据 */
    LOG_DEBUG(LOG_MODULE_NAME, "验证转换后的数据");
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象地址无效: %u", command->info_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    
    if (!is_scq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "单点命令品质描述词无效: 0x%02X", *(u8*)&command->quality);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    
    if (!is_cp56time2a_valid(&command->timestamp)) {
        LOG_ERROR(LOG_MODULE_NAME, "时间戳无效");
        return PROTOCOL_ERROR_DATA_INVALID_TIMESTAMP;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "带时标的单点命令转换成功: 地址=%u, 品质=0x%02X", 
             command->info_address, *(u8*)&command->quality);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证带时标的单点命令
 * @details 验证带时标的单点命令结构的完整性和有效性。
 *          检查地址、品质描述词和时间戳的有效性。
 * 
 * @param command 带时标的单点命令结构，不能为NULL
 * @return 验证结果
 *         - 1: 带时标的单点命令有效
 *         - 0: 带时标的单点命令无效
 * 
 * @note 验证地址、品质描述词和时间戳的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_info_address_valid
 * @see is_qos_valid
 * @see is_cp56time2a_valid
 * @see C_SC_TA_1_t
 */
int validate_single_command_with_time(const C_SC_TA_1_t* command) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证带时标的单点命令: command=%p", command);
    
    if (command == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "带时标的单点命令指针为NULL");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证信息对象地址: %u", command->info_address);
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象地址无效: %u", command->info_address);
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证单点命令品质");
    if (!is_scq_valid(&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "单点命令品质无效: 0x%02X", *(u8*)&command->quality);
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证时间戳");
    if (!is_cp56time2a_valid(&command->timestamp)) {
        LOG_ERROR(LOG_MODULE_NAME, "时间戳无效");
        return 0;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "带时标的单点命令验证成功: 地址=%u, 品质=0x%02X", 
             command->info_address, *(u8*)&command->quality);
    return 1;
}

/* ==================== 调节命令处理函数实现 ==================== */

/**
 * @brief 调节命令转换为字节数组
 * @details 将调节命令结构转换为104协议规定的字节数组格式。
 *          按照协议规范进行数据序列化。
 * 
 * @param command 调节命令结构，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_length 实际写入长度输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据序列化
 * @warning 缓冲区大小必须足够容纳转换后的数据
 * 
 * @see bytes_to_regulate_command
 * @see validate_regulate_command
 * @see buffer_write_u32
 * @see buffer_write_u16
 * @see buffer_write_u8
 */
protocol_error_t regulate_command_to_bytes(const C_RC_NA_1_t* command,
                                         u8* buffer, u32 buffer_size, u32* actual_length) {
    LOG_DEBUG(LOG_MODULE_NAME, "转换调节命令到字节数组: command=%p, buffer=%p, buffer_size=%u", 
              command, buffer, buffer_size);
    
    if (command == NULL || buffer == NULL || actual_length == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证调节命令 */
    LOG_DEBUG(LOG_MODULE_NAME, "验证信息对象地址: %u", command->info_address);
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象地址: %u", command->info_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象地址验证通过");
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证调节命令品质");
    if (!is_qoc_valid(*(uint8_t*)&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的调节命令品质");
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    LOG_DEBUG(LOG_MODULE_NAME, "调节命令品质验证通过");
    
    /* 检查缓冲区大小 */
    if (buffer_size < 6) { /* 地址(3字节) + 值(2字节) + QOC(1字节) */
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %u < 6", buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "开始写入调节命令数据到缓冲区");
    
    /* 写入信息对象地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入信息对象地址: %u", command->info_address);
    buffer_write_u32(buffer, 0, command->info_address, 0);
    
    /* 写入调节值 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入调节值: %d", command->value);
    buffer_write_u16(&buffer[3], 0, (u16)command->value, 0);
    
    /* 写入命令限定词 */
    LOG_DEBUG(LOG_MODULE_NAME, "写入命令限定词: 0x%02X", *(u8*)&command->quality);
    buffer[5] = *(u8*)&command->quality;
    
    *actual_length = 6;
    LOG_INFO(LOG_MODULE_NAME, "调节命令成功转换为字节数组，实际长度: %u", *actual_length);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 字节数组转换为调节命令
 * @details 将104协议规定的字节数组格式转换为调节命令结构。
 *          按照协议规范进行数据反序列化。
 * 
 * @param data 字节数组，不能为NULL
 * @param length 数据长度
 * @param command 调节命令结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 转换成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 数据长度不足
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 地址无效
 *         - PROTOCOL_ERROR_DATA_INVALID_VALUE: 数据值无效
 * 
 * @note 按照104协议规范进行数据反序列化
 * @warning 数据长度必须足够容纳调节命令
 * 
 * @see regulate_command_to_bytes
 * @see validate_regulate_command
 * @see buffer_read_u32
 * @see buffer_read_u16
 * @see buffer_read_u8
 */
protocol_error_t bytes_to_regulate_command(const u8* data, u32 length,
                                         C_RC_NA_1_t* command) {
    LOG_DEBUG(LOG_MODULE_NAME, "从字节数组转换调节命令: data=%p, length=%u, command=%p", 
              data, length, command);
    
    if (data == NULL || command == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 检查数据长度 */
    if (length < 6) { /* 地址(3字节) + 值(2字节) + QOC(1字节) */
        LOG_ERROR(LOG_MODULE_NAME, "数据长度太小: %u < 6", length);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "数据长度检查通过: %u >= 6", length);
    
    /* 读取信息对象地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取信息对象地址从缓冲区[0-2]");
    buffer_read_u32(data, 0, (u32*)&command->info_address, 0);
    
    /* 读取调节值 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取调节值从缓冲区[3-4]");
    buffer_read_u16(&data[3], 0, (u16*)&command->value, 0);
    
    /* 读取命令限定词 */
    LOG_DEBUG(LOG_MODULE_NAME, "读取命令限定词从缓冲区[5]");
    memcpy(&command->quality, &data[5], sizeof(qoc_t));
    
    LOG_DEBUG(LOG_MODULE_NAME, "读取完成: 地址=%u, 值=%d, QOC=0x%02X", 
              command->info_address, command->value, *(u8*)&command->quality);
    
    /* 验证转换后的数据 */
    LOG_DEBUG(LOG_MODULE_NAME, "验证转换后的数据");
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象地址无效: %u", command->info_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    
    if (!is_qoc_valid(*(uint8_t*)&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "命令限定词无效: 0x%02X", *(u8*)&command->quality);
        return PROTOCOL_ERROR_DATA_INVALID_VALUE;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "调节命令转换成功: 地址=%u, 值=%d, QOC=0x%02X", 
             command->info_address, command->value, *(u8*)&command->quality);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证调节命令
 * @details 验证调节命令结构的完整性和有效性。
 *          检查地址、数值和命令限定词的有效性。
 * 
 * @param command 调节命令结构，不能为NULL
 * @return 验证结果
 *         - 1: 调节命令有效
 *         - 0: 调节命令无效
 * 
 * @note 验证地址、数值和命令限定词的有效性
 * @warning 输入指针不能为NULL
 * 
 * @see is_info_address_valid
 * @see is_qoc_valid
 * @see C_RC_NA_1_t
 */
int validate_regulate_command(const C_RC_NA_1_t* command) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证调节命令: command=%p", command);
    
    if (command == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "调节命令指针为NULL");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证信息对象地址: %u", command->info_address);
    if (!is_info_address_valid(command->info_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象地址无效: %u", command->info_address);
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "验证命令限定词");
    if (!is_qoc_valid(*(uint8_t*)&command->quality)) {
        LOG_ERROR(LOG_MODULE_NAME, "命令限定词无效: 0x%02X", *(u8*)&command->quality);
        return 0;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "调节命令验证成功: 地址=%u, 值=%d, QOC=0x%02X", 
             command->info_address, command->value, *(u8*)&command->quality);
    return 1;
}

/* ==================== 辅助函数实现 ==================== */

/**
 * @brief 获取单点命令大小
 * @details 获取单点命令结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @return 单点命令大小（字节）
 * 
 * @note 单点命令大小：4字节（地址3字节 + SCQ1字节）
 * @warning 此函数是线程安全的
 * 
 * @see get_double_command_size
 * @see get_single_command_with_time_size
 * @see C_SC_NA_1_t
 */
u32 get_single_command_size(void) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取单点命令大小");
    u32 size = 4; /* 地址(3字节) + SCQ(1字节) */
    LOG_INFO(LOG_MODULE_NAME, "单点命令大小: %u字节", size);
    return size;
}

/**
 * @brief 获取双点命令大小
 * @details 获取双点命令结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @return 双点命令大小（字节）
 * 
 * @note 双点命令大小：4字节（地址3字节 + DCQ1字节）
 * @warning 此函数是线程安全的
 * 
 * @see get_single_command_size
 * @see get_double_command_with_time_size
 * @see C_DC_NA_1_t
 */
u32 get_double_command_size(void) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取双点命令大小");
    u32 size = 4; /* 地址(3字节) + DCQ(1字节) */
    LOG_INFO(LOG_MODULE_NAME, "双点命令大小: %u字节", size);
    return size;
}

/**
 * @brief 获取带时标的单点命令大小
 * @details 获取带时标的单点命令结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @return 带时标的单点命令大小（字节）
 * 
 * @note 带时标的单点命令大小：11字节（地址3字节 + SCQ1字节 + 时间戳7字节）
 * @warning 此函数是线程安全的
 * 
 * @see get_single_command_size
 * @see get_double_command_with_time_size
 * @see C_SC_TA_1_t
 */
u32 get_single_command_with_time_size(void) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取带时标的单点命令大小");
    u32 size = 11; /* 地址(3字节) + SCQ(1字节) + 时间戳(7字节) */
    LOG_INFO(LOG_MODULE_NAME, "带时标的单点命令大小: %u字节", size);
    return size;
}

/**
 * @brief 获取调节命令大小
 * @details 获取调节命令结构在字节数组中的大小。
 *          用于缓冲区大小计算。
 * 
 * @return 调节命令大小（字节）
 * 
 * @note 调节命令大小：6字节（地址3字节 + 值2字节 + QOC1字节）
 * @warning 此函数是线程安全的
 * 
 * @see get_single_command_size
 * @see get_double_command_size
 * @see C_RC_NA_1_t
 */
u32 get_regulate_command_size(void) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取调节命令大小");
    u32 size = 6; /* 地址(3字节) + 值(2字节) + QOC(1字节) */
    LOG_INFO(LOG_MODULE_NAME, "调节命令大小: %u字节", size);
    return size;
}

/* ==================== 品质描述词验证函数实现 ==================== */

/**
 * @brief 验证单点命令品质描述词
 * @details 验证SCQ（单点命令品质描述词）是否在104协议规定的有效范围内。
 *          检查保留位是否都为0。
 * 
 * @param scq 单点命令品质描述词
 * @return 验证结果
 *         - 1: SCQ有效
 *         - 0: SCQ无效
 * 
 * @note SCQ只有1位有效，其他位必须为0
 * @warning 保留位必须为0
 * 
 * @see is_diq_valid
 * @see is_qoc_valid
 * @see scq_t
 */
int is_scq_valid(const scq_t* scq) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证单点命令品质描述词: scq=%p", scq);
    
    if (scq == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "单点命令品质描述词指针为NULL");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "检查SCQ保留位: res=%d, bl=%d, sb=%d, nt=%d, iv=%d", 
              scq->res, scq->bl, scq->sb, scq->nt, scq->iv);
    
    /* SCQ只有1位有效，其他位必须为0 */
    int valid = ((scq->res == 0) && (scq->bl == 0) && (scq->sb == 0) && 
                 (scq->nt == 0) && (scq->iv == 0));
    
    if (valid) {
        LOG_INFO(LOG_MODULE_NAME, "单点命令品质描述词验证成功");
    } else {
        LOG_ERROR(LOG_MODULE_NAME, "单点命令品质描述词验证失败: 保留位不为0");
    }
    
    return valid;
}

/**
 * @brief 验证双点命令品质描述词
 * @details 验证DCQ（双点命令品质描述词）是否在104协议规定的有效范围内。
 *          检查保留位是否都为0。
 * 
 * @param dcq 双点命令品质描述词
 * @return 验证结果
 *         - 1: DCQ有效
 *         - 0: DCQ无效
 * 
 * @note DCQ只有2位有效，其他位必须为0
 * @warning 保留位必须为0
 * 
 * @see is_qos_valid
 * @see is_qoc_valid
 * @see dcq_t
 */
int is_dcq_valid(const dcq_t* dcq) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证双点命令品质描述词: dcq=%p", dcq);
    
    if (dcq == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "双点命令品质描述词指针为NULL");
        return 0;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "检查DCQ保留位: res=%d, bl=%d, sb=%d, nt=%d, iv=%d", 
              dcq->res, dcq->bl, dcq->sb, dcq->nt, dcq->iv);
    
    /* DCQ只有2位有效，其他位必须为0 */
    int valid = ((dcq->res == 0) && (dcq->bl == 0) && (dcq->sb == 0) && 
                 (dcq->nt == 0) && (dcq->iv == 0));
    
    if (valid) {
        LOG_INFO(LOG_MODULE_NAME, "双点命令品质描述词验证成功");
    } else {
        LOG_ERROR(LOG_MODULE_NAME, "双点命令品质描述词验证失败: 保留位不为0");
    }
    
    return valid;
}
